﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Noris.Schedule.Support
{
	public static class Reflect
	{
		/// <summary>
		/// Načte informace o všech objektech, které jsou IElementPainter, ze všech Assembly z DLL
		/// </summary>
		/// <param name="findType">Jméno typu, který hledám</param>
		public static List<Type> LoadTypeWithInterface(Type findType)
		{
			List<Type> result = new List<Type>();
			Assembly assembly = Assembly.GetExecutingAssembly();
			//_LoadTypeWithInterfaceOne(assembly, findType, ref result);

			string location = assembly.Location;
			string path = System.IO.Path.GetDirectoryName(location);
			System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(path);
			System.IO.FileInfo[] files = di.GetFiles("*.*");
			foreach (System.IO.FileInfo file in files)
			{
				string ext = file.Extension.ToLower();
				if (ext == ".dll" || ext == ".exe")
				{
					Assembly ass = Assembly.LoadFile(file.FullName);
					_LoadTypeWithInterfaceOne(ass, findType, ref result);
				}
			}
			return result;
		}
		/// <summary>
		/// Načte informace o všech objektech, které jsou IElementPainter, v dané Assembly
		/// </summary>
		/// <param name="assembly">Assembly, kde se hledá</param>
		/// <param name="findType">Jméno typu, který hledám</param>
		private static void _LoadTypeWithInterfaceOne(Assembly assembly, Type findType, ref List<Type> result)
		{
			string findIfName = findType.Name;                       // Jméno typu, který hledám
			List<Type> types = new List<Type>(assembly.GetTypes());  // Soupis všech typů (třídy, struktury, interface, enumy, atd atd)
			foreach (Type type in types)
			{
				if (!type.IsClass) continue;                         // Pokud nalezený typ není class, jdi na další. Testujeme jen třídy.
				if (!TestTypeImplementInterface(type, findType)) continue;
				result.Add(type);
			}
		}
		public static List<T> ActivateTypes<T>(IEnumerable<Type> typeList)
		{
			List<T> result = new List<T>();
			foreach (Type type in typeList)
				result.Add((T)System.Activator.CreateInstance(type, false));
			return result;


		}
		/// <summary>
		/// Metoda zjistí, zda daný typ (dataType) implementuje daný interface.
		/// Oba typy jsou předané jako proměnné, to je důvod existence této metody.
		/// </summary>
		/// <param name="dataType">Typ testované třídy</param>
		/// <param name="interfaceType">Typ interface, které hledáme</param>
		/// <returns>true: testovaný typ implementuje daný interface</returns>
		public static bool TestTypeImplementInterface(Type dataType, Type interfaceType)
		{
			Type[] inf = dataType.FindInterfaces(delegate(Type t, object data) { return (t.FullName == ((Type)data).FullName); }, interfaceType);
			return (inf.Length > 0);
		}
	}
}
